#include "stdafx.h"
#include "Cutit.hpp"
#include "../environment/Map.hpp"

namespace actors
{

void Cutit::UpdateFights()
{
    Generik * closerEnemy = this->GetCloserEnemy();

    if( closerEnemy == NULL )
        return;

    int numBall = headCollideWith( *closerEnemy );
    if( numBall > 0  )
    {
        cutInTwo( closerEnemy, numBall );
        m_isCuting = true;
        m_cuttingTime = 0;
    }
}
void Cutit::UpdateCutit()
{
    m_endTime = clock();
    while ( !m_isDead )
    {
        m_timeDelta = ( (m_endTime - m_beginTime) > 0 ? (m_endTime - m_beginTime) : 1 ) / 1000.0f;
        m_beginTime = clock();

        this->move();
        if ( !m_isCuting )
        {
            this->UpdateFights();
        }

        boost::shared_ptr< Event::EventChangePosition > changePos = boost::make_shared< network::packet::RequestChangePosition >( m_id, m_position );
        POST_EVENT( changePos );

        m_cuttingTime += m_timeDelta;
        if ( m_cuttingTime > 500 )
        {
            m_isCuting = false;
        }
        m_endTime = clock();
    }
}

int Cutit::headCollideWith( const Generik& _generik )
{
    irr::core::vector3df posGenerik( _generik.getPosition() );
    irr::core::vector3df negDirGenerik( -_generik.getDirection() );
    negDirGenerik.normalize();
    float midRadius = _generik.getMidRadius();
    float radius = _generik.getRadius();
    float myMidRadius = m_radius/2.0f;
    boost::uint8_t ageGenerik( _generik.getAge() );

    bool collide = false;
    int ball = -1;
    while ( ball <= ageGenerik && !collide )
    {
        if ( (posGenerik - m_position).getLength() <= (myMidRadius + midRadius) )
        {
            collide = true;
        }
        else
        {
            ++ball;

            posGenerik += negDirGenerik * radius;
        }
    }

    if ( ball > ageGenerik )
    {
        return -1;
    }

    return ball;
}

void Cutit::cutInTwo( Generik* _generikToCut, int _numBall )
{
    irr::core::vector3df direction( _generikToCut->getDirection() );
    direction.normalize();
    irr::core::vector3df positionFront( _generikToCut->getPosition() );
    irr::core::vector3df positionBack( direction * _numBall * (-1.0f) + positionFront );
    int age = _generikToCut->getAge();

    environment::Map * map = environment::Map::getSingletonPtr();

    _generikToCut->cut( positionFront, _numBall-1, positionBack, age - (_numBall-1) );

    /*std::cout << "cut in two : " << positionFront.X << "," << positionFront.Y << positionFront.Z << " aged " << (_numBall-1) 
        << ", and : " << positionBack.X << "," << positionBack.Y << positionBack.Z << " aged " << (age - (_numBall-1)) << std::endl;*/
}

Cutit::Cutit( const irr::core::vector3df& _Pos, const irr::core::vector3df& _Dir ) :
    m_id(0),
    m_age(3),
    m_radius(20.0f),
    m_maxVelocity(2.0f),
    m_direction(_Dir),    
    m_position(_Pos),
    m_isDead(false),
    m_infiniteLoopCounter(0),
    m_isCuting(false)
{
    m_direction.normalize();
}
Cutit::~Cutit()
{
    Event::EventManager::getSingleton().destroyAllConnections( this );
}
irr::core::vector3df Cutit::GetBoudingCircleCenter()
{
    irr::core::vector3df pos = this->m_position;
    float NB_Cercle = this->m_age;
    irr::core::vector3df posFin = m_position - (m_direction* NB_Cercle * m_radius);

    return m_position + ( (posFin-m_position)/2 );
}
float Cutit::GetBoudingCircleSize()
{
    return m_radius/2.0f + (m_age/2.0);
}
irr::core::vector3df Cutit::GetEndPosition()
{
    irr::core::vector3df _Pos = this->m_position;
    float NB_Cercle = this->m_age;
    irr::core::vector3df _PosFin = m_position - (m_direction* NB_Cercle * m_radius);

    return m_position + ( (_PosFin-m_position) );
}
// fct pour la simu
void Cutit::move()
{
    m_direction.normalize();
    irr::core::vector3df NewPos = m_position + ( m_direction*m_maxVelocity * m_timeDelta );
    //printf("%f\n",m_timeDelta);

    if( environment::Map::getSingleton().GetCollision( (int)NewPos.X, (int)NewPos.Z ) == false ) // si pas de colli
    {
        m_position = NewPos;

        m_infiniteLoopCounter = 0;
    }
    else // si colli
    {
        m_direction = irr::core::vector3df( RAND(-10,10) + 0.1 - m_direction.X * 10.0f, 0.0f, RAND(-10,10)+ 0.1  - m_direction.Z * 10.0f );
        m_direction.normalize();

        m_infiniteLoopCounter++;

        if( m_infiniteLoopCounter > 6 )
            return;
        /*	
        if( ((int)m_position.X()) ==  ((int)NewPos.X()) )
        {
        m_direction.Y() *= -1;
        printf("Inverse Y\n");
        }
        else if( ((int)m_position.Y()) ==  ((int)NewPos.Y()) )
        {
        m_direction.X() *= -1;
        printf("Inverse X\n");
        }
        else
        {
        m_direction.X() *= -1;
        m_direction.Y() *= -1;
        printf("Inverse X et Y\n");
        }
        */

        move();
    }

    //environment::Map::getSingleton().addBourikScent( 100 , i, 25+i );
}

    Generik* Cutit::GetCloserEnemy()
    {        
        Generik* Res = environment::Map::getSingleton().getCloserGenerik( this );

        return Res;
    }

    }